图论

图论基础


图的存储


邻接表存图

对于每一个节点,记录这个几点连接的所有其他节点和对应权值

#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
vector<pair<ll,int> graph[N];//图,{权值,对应的节点}
int n,m;
int main(){
    cin>>n>>m;
    for(int i = 0;i<m;i++){
        int u,v,w;
        cin>>u>>v>>w;
        graph[u].push_back({w,v});
        graph[v].push_back({w,u});
    }
}

邻接矩阵存图

用一个二维数组记录每两个点之间的距离

两个索引分别代表两个点 g[i][j]的值代表点i和j之间的距离

#define ll long long
const int N = 200010;
const ll INF = 4e18;
ll g[N][N];
int main(){
    int n,m;
    cin>>n>>m;
    for(int i = 1;i<=n;i++){
        for(int j = 1;j<=n;j++){
            if(i==j){
                g[i][j] = 0;//同一个点当然是0
            }else{
                g[i][j] = INF;//初始化矩阵为INF(不可达)
            }
        }
    }
    for(int i = 0;i<m;i++){
        int u,v;
        ll w;
        cin>>u>>v>>w;
        //无向图
        g[u][v] = min(g[u][v],w);
        g[v][u] = min(g[v][u],w);//注意 这里出现重边时取用min是绝大部分情况 不排除其他写法
        //如果是有向图,只用下面这一行
        //g[u][v] = min(g[u][v],w);
    }
}

稠密图&稀疏图

令n=点数 m=边数

因此无向图最大边数=(n*(n-1))/2

如果m接近于这个最大边数 就是稠密图

如果m接近n或者更小 就是稀疏图

可以根据稀疏和稠密的性质选择算法 获得更高效率


最小生成树

复杂度

一般来说

另外:

选择Kruskal和堆优化Prim在复杂度上没有差异

但是Kruskal是基于sort排序和并查集 更快且不容易写错

选择Kruskal